package com.xunyji.demo03.realm;

import com.xunyji.demo0.StringUtilsXyj;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * @author AltEnter
 * @create 2019-01-23 15:35
 * @desc 自定义Realm
 **/
public class CustomRealm extends AuthorizingRealm {

//    模拟数据库
    private Map<String, String> userMap = new HashMap();

    {
        super.setName("CustomRealm");
//        userMap.put("fury", "111111");
//        userMap.put("fury", "96e79218965eb72c92a549dd5a330112");
        userMap.put("fury", "66b747dd6c7c7c8ca4227a67fff8ea6e");
    }

    /**
     * 授权逻辑
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//        获取用户名
        String username = (String) principals.getPrimaryPrincipal();
//        根据用户名获取角色信息
        Set<String> roleSet = getRoleSetByUsername(username);
//        根据用户名获取权限信息
        Set<String> permissionSet = getPermissionSetByUsername(username);
//        授权信息封装
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setRoles(roleSet);
        simpleAuthorizationInfo.setStringPermissions(permissionSet);
        return simpleAuthorizationInfo;
    }

    /**
     * 根据用户名获取权限集合
     * @param username
     * @return
     */
    private Set<String> getPermissionSetByUsername(String username) {
        HashSet<String> permissionSet = new HashSet<String>();
        permissionSet.add("user:create");
        permissionSet.add("user:delete");
        return permissionSet;
    }

    /**
     * 根据用户名获取角色集合
     * @param username
     * @return
     */
    private Set<String> getRoleSetByUsername(String username) {
        HashSet<String> roleSet = new HashSet<String>();
        roleSet.add("admin");
        roleSet.add("user");
        return roleSet;
    }

    /**
     * 认证逻辑
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//        获取用户名
        String username = (String) token.getPrincipal();
//        获取密码
        String password = new String((char[]) token.getCredentials());
        if (StringUtilsXyj.isEmpty(username) || StringUtilsXyj.isEmpty(password)) {
            throw new RuntimeException("doGetAuthenticationInfo - 用户名和密码不能为空");
        }
        System.out.println(String.format("doGetAuthenticationInfo - 前端传过来的用户信息 - 用户名为：%s, 用户密码为：%s", username, password));
//        密码加密加盐
        password = string2Md5Hash(password, "AltEnter");
        System.out.println(String.format("doGetAuthenticationInfo - 前端密码加密后的结果为：%s", password));
//        根据用户名获取数据库中的密码
        String pwd = getPasswordByUsername(username);
        if (password.equals(pwd)) {
//            认证信息封装
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password, getName());
//            设置salt
            simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("AltEnter"));
            return simpleAuthenticationInfo;
        } else {
            throw new RuntimeException("doGetAuthenticationInfo - 用户名或者密码错误");
        }
    }

    /**
     * 密码加密加盐处理
     * @param password 待加密密码
     * @param salt 盐
     * @return 经过加密和加盐处理后的密码
     */
    private String string2Md5Hash(String password, String salt) {
        return new Md5Hash(password, salt).toString();
    }

    /**
     * 根据用户名获取用户密码
     * @param username
     * @return
     */
    private String getPasswordByUsername(String username) {
        return userMap.get(username);
    }

    public static void main(String[] args) {
//        Md5Hash md5Hash = new Md5Hash("111111");
//        System.out.println("111111加密后的结果为：" + md5Hash.toString());
//        96e79218965eb72c92a549dd5a330112

        Md5Hash md5Hash = new Md5Hash("111111", "AltEnter");
        System.out.println("111111经过MD5加密和AltEnter加盐后的结果为：" + md5Hash.toString());
//        66b747dd6c7c7c8ca4227a67fff8ea6e
    }

}

